﻿namespace Services
{
    public interface IRepository<TEntity>
        where TEntity : BaseEntity, new()
    {
        #region 添加
        int Insert(TEntity entity);
        int BatchInsert(List<TEntity> entities);
        #endregion

        #region 修改
        int Update(TEntity entity);
        int BatchUpdate(List<TEntity> entities);
        #endregion

        #region 删除
        int Delete(int id);
        int BatchDelete(List<int> ids);
        #endregion

        #region 查询
        TEntity GetByID(int id);
        TEntity GetModel(Expressionable<TEntity> where, string orderBy = null);
        List<TEntity> GetAll(string orderBy = null);
        List<TEntity> GetSearch(Expressionable<TEntity> where, string orderBy = null, int? top = null);
        (List<TEntity> items, int totalCount) GetPage(Expressionable<TEntity> where, int pageIndex = 1, int pageSize = Gx._PAGE_SIZE, string orderBy = null);
        int GetCount(Expressionable<TEntity> where);
        #endregion

        #region 使用SQL语句查询
        TEntity GetModelBySQL(string sql, List<SugarParameter> values = null);
        List<TEntity> GetSearchBySQL(string sql, List<SugarParameter> values = null);
        int GetCountBySQL(string sql, List<SugarParameter> values = null);
        #endregion

        #region 执行SQL语句并返回首行首列的值
        int ExecuteNonQueryBySQL(string sql, List<SugarParameter> values = null);
        int ExecuteScalarIntBySQL(string sql, List<SugarParameter> values = null);
        string ExecuteScalarStringBySQL(string sql, List<SugarParameter> values = null);
        object ExecuteScalarObjectBySQL(string sql, List<SugarParameter> values = null);
        #endregion
    }

    public class BaseRepository<TEntity> : IRepository<TEntity>
         where TEntity : BaseEntity, new()
    {
        #region Ioc
        public readonly ISqlSugarClient _DB;
        public readonly ICurrentUser _currentUser;
        public readonly IQuery<TEntity> _query;

        public BaseRepository(ISqlSugarClient dB, ICurrentUser currentUser, IQuery<TEntity> query)
        {
            _DB = dB;
            _currentUser = currentUser;
            _query = query;
        }
        #endregion

        #region 添加
        public virtual int Insert(TEntity entity)
        {
            SetInsertInfo(entity);
            return _DB.Insertable(entity).ExecuteReturnIdentity();
        }

        public virtual int BatchInsert(List<TEntity> entities)
        {
            SetInsertInfo(entities.ToArray());
            return _DB.Insertable(entities).ExecuteCommand();
        }
        #endregion

        #region 修改
        public virtual int Update(TEntity entity)
        {
            SetUpdateInfo(entity);
            return _DB.Updateable(entity).ExecuteCommand();
        }

        public virtual int BatchUpdate(List<TEntity> entities)
        {
            SetUpdateInfo(entities.ToArray());
            return _DB.Updateable(entities).ExecuteCommand();
        }
        #endregion

        #region 删除
        public virtual int Delete(int id)
        {
            return _DB.Deleteable<TEntity>(id).ExecuteCommand();
        }

        public virtual int BatchDelete(List<int> ids)
        {
            return _DB.Deleteable<TEntity>(ids).ExecuteCommand();
        }
        #endregion

        #region 查询
        public virtual TEntity GetByID(int id)
        {
            return _query.GetByID(id);
        }

        public virtual TEntity GetModel(Expressionable<TEntity> where, string orderBy = null)
        {
            return _query.GetModel(where, orderBy);
        }

        public virtual List<TEntity> GetAll(string orderBy = null)
        {
            return _query.GetAll(orderBy);
        }

        public virtual List<TEntity> GetSearch(Expressionable<TEntity> where, string orderBy = null, int? top = null)
        {
            return _query.GetSearch(where, orderBy, top);
        }

        public virtual (List<TEntity> items, int totalCount) GetPage(Expressionable<TEntity> where, int pageIndex = 1, int pageSize = Gx._PAGE_SIZE, string orderBy = null)
        {
            return _query.GetPage(where, pageIndex, pageSize, orderBy);
        }

        public virtual int GetCount(Expressionable<TEntity> where)
        {
            return _query.GetCount(where);
        }
        #endregion

        #region 使用SQL语句查询
        public virtual TEntity GetModelBySQL(string sql, List<SugarParameter> values = null)
        {
            return _query.GetModelBySQL(sql, values);
        }

        public virtual List<TEntity> GetSearchBySQL(string sql, List<SugarParameter> values = null)
        {
            return _query.GetSearchBySQL(sql, values);
        }

        public virtual int GetCountBySQL(string sql, List<SugarParameter> values = null)
        {
            return _query.GetCountBySQL(sql, values);
        }
        #endregion

        #region 执行SQL语句并返回首行首列的值
        public virtual int ExecuteNonQueryBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.ExecuteCommand(sql, values);
        }

        public virtual int ExecuteScalarIntBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.GetInt(sql, values);
        }

        public virtual string ExecuteScalarStringBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.GetString(sql, values);
        }

        public virtual object ExecuteScalarObjectBySQL(string sql, List<SugarParameter> values = null)
        {
            return _DB.Ado.GetScalar(sql, values);
        }
        #endregion

        


        #region 私有方法  处理特殊字段
        private void SetInsertInfo(params TEntity[] entities)
        {
            if (_currentUser.CurrentUserInfo.IsEmpty() || _currentUser.CurrentUserInfo.UserID == 0)
            {
                return;
            }

            var now = DateTime.Now;

            foreach (var entity in entities)
            {
                typeof(TEntity).GetProperty(Gx._DB_FIELD_NAME_KEY)?.SetValue(entity, _currentUser.CurrentUserInfo.LoginTypeID);

                typeof(TEntity).GetProperty("CreateUserID")?.SetValue(entity, _currentUser.CurrentUserInfo.UserID);
                typeof(TEntity).GetProperty("CreateUserName")?.SetValue(entity, _currentUser.CurrentUserInfo.UserName);
                typeof(TEntity).GetProperty("CreateDate")?.SetValue(entity, now);

                typeof(TEntity).GetProperty("UpdateUserID")?.SetValue(entity, _currentUser.CurrentUserInfo.UserID);
                typeof(TEntity).GetProperty("UpdateUserName")?.SetValue(entity, _currentUser.CurrentUserInfo.UserName);
                typeof(TEntity).GetProperty("UpdateDate")?.SetValue(entity, now);
            }
        }

        private void SetUpdateInfo(params TEntity[] entities)
        {
            if (_currentUser.CurrentUserInfo.IsEmpty() || _currentUser.CurrentUserInfo.UserID == 0)
            {
                return;
            }

            var now = DateTime.Now;

            foreach (var entity in entities)
            {
                typeof(TEntity).GetProperty("UpdateUserID")?.SetValue(entity, _currentUser.CurrentUserInfo.UserID);
                typeof(TEntity).GetProperty("UpdateUserName")?.SetValue(entity, _currentUser.CurrentUserInfo.UserName);
                typeof(TEntity).GetProperty("UpdateDate")?.SetValue(entity, now);
            }
        }
        #endregion
    }
}
